home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / change.cq / change.c
Text File  |  1985-07-06  |  8KB  |  292 lines

  1. /*
  2.                   Change - text file line changer
  3.  
  4. last modified : 23 October 1983
  5.  
  6. usage: Change <from_string> <to_string> <filename> [<file2> <filen> -d -n -q -r]
  7.  
  8. Warning: generic filenames (* and ?) not implemented with CI-C86.
  9.  
  10. Change is a text search and replace program for multiple files.  It 
  11. is useful for replacing text strings common to a batch of files, 
  12. for instance all the source files for a long program.
  13.  
  14. The command line file specifer(s) may be one or more ambiguous or 
  15. non-ambiguous file names.
  16.  
  17. For example:
  18.  
  19.   Change from to foo                <- chg operates on the file foo only
  20.   Change from to foo bar.*          <- operates on the files foo, and any
  21.                                     expansions of bar.*
  22.   Change from to *.c??              <- chg operates on all files of type c
  23.   Change from to *.c*               <- same as above
  24.  
  25. The command line dash options are:
  26.      -d(isplay)           <- display all changes on the  console
  27.                              as they occur
  28.      -n(o line numbers)      <- turns  line  numbering  off   (only
  29.                              valid with -d option
  30.      -q(uery)             <- prompt and ask  before  each  change
  31.      -r(etain original)   <- output (for each input file) goes to
  32.                              the (created) file <infile.$$>  (the
  33.                              '$$' extention is added)
  34.                              in default operation,  the  original
  35.                              file  is  rename  to  type 'BAK' and
  36.                              output goes to a newly created  file
  37.                              with  the  same name as the original
  38.                              input file.
  39.  
  40.    Copyright (c) 1983 by
  41.    Tony Rowe
  42.    3260 So. Penn
  43.    Englewood, Co.  80110
  44.   
  45.    (303) 761-0755
  46.  */
  47.  
  48. #include <stdio.h>
  49. #define TRUE 1
  50. #define FALSE 0
  51. #define ERROR (-1)
  52.  
  53. #define MAXLEN 300
  54. #define bool char
  55. #define INPUT "r"
  56. #define OUTPUT "w"
  57. #define DEFTYP ".$$"
  58. #define BAKTYP ".BAK"
  59. #define YES TRUE
  60. #define NO FALSE
  61.  
  62. /* externals used mainly for the sake of speed */
  63. FILE *InFile;                /* disk file pointers */
  64. FILE *OutFile;
  65. char LineBuffer[2*MAXLEN];        /* line buffer */
  66. char SearchPattern[MAXLEN];        /* search pattern buffer */
  67. char ReplacementPattern[MAXLEN];    /* replace pattern string buffer */
  68. char *Cp;                /* general purpose character pointer */
  69. int Line;                /* line number */
  70. bool ShowLineNumbers, ShowChanges,    /* option flags */
  71.      AskBeforeChanging, RetainOriginalFile;
  72.  
  73. main(argc, argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.     char OutFName[MAXLEN];        /* output file name buffer */
  78.     char BackupFName[MAXLEN];    /* backup file name buffer */
  79.     char RestOfString[2*MAXLEN];    /* rest of string buffer */
  80.     short arg;            /* argv index */
  81.     int ChangeFile();        /* routine to change strings */
  82.  
  83.     "Copyright (c) 1983 by Tony Rowe";
  84.  
  85.     ShowChanges = AskBeforeChanging = RetainOriginalFile = FALSE;
  86.     ShowLineNumbers = TRUE;
  87.  
  88.     if (argc < 4) {
  89.         printf("%s\n%s\n",
  90.          "Usage: Change from_string to_string filename [filename...]",
  91.          "\t[-d(isplay) -n(o numbers) -q(uery) -r(etain original)]");
  92.         exit();
  93.     }
  94.  
  95. #ifdef CONSOLE
  96.     printf("\nSearch pattern: ");
  97.     fgets(SearchPattern, MAXLEN, stdin);
  98.     if (SearchPattern[0] == '\0')
  99.         exit();
  100.     printf("Replacement pattern: ");
  101.     fgets(ReplacementPattern, MAXLEN, stdin);
  102. #else /* not CONSOLE */
  103.     strcpy(SearchPattern, argv[1]);
  104.     strcpy(ReplacementPattern, argv[2]);
  105.     if (! strcmp(ReplacementPattern, "\"\""))
  106.         strcpy(ReplacementPattern, "");
  107. #endif /* def CONSOLE */
  108.  
  109.     /* check args for options */
  110.     for (arg = 1; arg < argc; ++arg) {
  111.         if (argv[arg][0] == '-') {
  112.             switch (toupper(argv[arg][1])) {
  113.             case 'N':
  114.                 ShowLineNumbers = FALSE;
  115.                 continue;
  116.             case 'Q':
  117.                 AskBeforeChanging = TRUE;
  118.             case 'D':
  119.                 ShowChanges = TRUE;
  120.                 continue;
  121.             case 'R':
  122.                 RetainOriginalFile = TRUE;
  123.                 continue;
  124.             default:
  125.                 printf("\nBad option: %s\n", argv[arg]);
  126.             }
  127.         }
  128.     }
  129.  
  130.     /* process filenames from command line, skipping '-' options */
  131.     for (arg = 3; arg < argc; ++arg) {
  132.         if (argv[arg][0] == '-') {
  133.             switch (toupper(argv[arg][1])) {
  134.             case 'D':
  135.             case 'N':
  136.             case 'Q':
  137.             case 'R':
  138.                 continue;
  139.             } /* switch */
  140.         } /* if */
  141.         ProcessFiles(argv[arg], ChangeFile);
  142.     } /* for */
  143. } /* main () */
  144.  
  145.  
  146. ChangeFile (FileName)
  147. char *FileName;
  148. {
  149.     char OutFName[MAXLEN];        /* output file name buffer */
  150.     char BackupFName[MAXLEN];    /* backup file name buffer */
  151.     char RestOfString[2*MAXLEN];    /* rest of string buffer */
  152.     int PatternLength;        /* length of replacement pattern */
  153.     bool FoundSearchPattern;    /* save output file flag */
  154.  
  155.     "Copyright (c) 1983 by Tony Rowe";
  156.  
  157.     /* don't process any .COM files */
  158.     for (Cp = FileName; *Cp != '\0' && *Cp != '.'; ++Cp)
  159.         ;
  160.     if (! strcmp(Cp, ".COM"))
  161.         return;
  162.  
  163.     if ((InFile = fopen(FileName, INPUT)) == NULL) {
  164.         printf("\nNo file: %s\n", FileName);
  165.         return;
  166.     }
  167.     /* make output filenames */
  168.     strcpy(OutFName, FileName);
  169.     for (Cp = OutFName; *Cp != '\0' && *Cp != '.'; ++Cp)
  170.         ;
  171.     *Cp = '\0';
  172.     strcpy(BackupFName, OutFName);
  173.     strcat(OutFName, DEFTYP);
  174.     strcat(BackupFName, BAKTYP);
  175.  
  176.     if ((OutFile = fopen(OutFName, OUTPUT)) == NULL)
  177.         exit(printf("Can't create: %s\n", OutFName));
  178.  
  179.     PatternLength = strlen(SearchPattern);
  180.     FoundSearchPattern = NO;
  181.  
  182.     for (Line = 0; fgets(LineBuffer, MAXLEN, InFile); ++Line) {
  183.         for (Cp = LineBuffer; *Cp; ++Cp) {
  184.             if (strmatch(Cp, SearchPattern)) {
  185.                 if ( (! FoundSearchPattern) && ShowChanges)
  186.                     printf("\n%s\n", FileName);
  187.                 FoundSearchPattern = YES;
  188.                 if (ShowChanges) {
  189.                     ShowLineNumbers?
  190.                      printf("\n%05d:  %s", Line, LineBuffer):
  191.                      printf(LineBuffer);
  192.                     if (AskBeforeChanging) {
  193.                         putpointer(LineBuffer, Cp - LineBuffer,
  194.                  ShowLineNumbers? 8: 0);
  195.                         if (! askyn("  Change"))
  196.                             continue;
  197.                     }
  198.                 }
  199.                 strcpy(RestOfString, Cp + PatternLength);
  200.                 strcpy(Cp, ReplacementPattern);
  201.                 Cp += PatternLength + 1;
  202.                 strcat(LineBuffer, RestOfString);
  203.                 if (ShowChanges) {
  204.                      ShowLineNumbers?
  205.                      printf("%05d:  %s", Line, LineBuffer):
  206.                      printf(LineBuffer);
  207.                 }
  208.         }
  209.         }
  210.         if (fputs(LineBuffer, OutFile) == ERROR) {
  211.         printf("Error writing a line to: %s\n", OutFName);
  212.         exit();
  213.         }
  214.     }
  215.  
  216.     fclose(InFile);
  217.  
  218.     if (FoundSearchPattern) {
  219.         if (fclose(OutFile) == ERROR) {
  220.             printf("Can't close: %s\n", OutFName);
  221.             exit();
  222.         }
  223.         if (RetainOriginalFile) {
  224.             unlink(BackupFName);
  225.             rename(FileName, BackupFName);
  226.             rename(OutFName, FileName);
  227.         }
  228.         else {
  229.             unlink(FileName);
  230.             rename(OutFName, FileName);
  231.         }
  232.     }
  233.     else {
  234.         fclose(OutFile);
  235.         unlink(OutFName);
  236.     }
  237. } /* ChangeFile () */
  238.  
  239.  
  240. strmatch(str, pat)
  241. char *str, *pat;
  242. {
  243.     while (*pat)
  244.         if (*str++ != *pat++)
  245.             return NO;
  246.     return YES;
  247. }
  248.  
  249. askyn(prompt)
  250. char *prompt;
  251. {
  252.     while (TRUE) { /* forever */
  253.         printf(prompt);
  254.         printf(" ?  ");
  255.         switch (GetInKey()) {
  256.         case 'y':
  257.         case 'Y':
  258.             printf("yes\t\t\n");
  259.             return YES;
  260.         case 'n':
  261.         case 'N':
  262.             printf("no\t\t\n");
  263.             return NO;
  264.         case '\3': /* control-C */
  265.             printf("^C");
  266.             exit();
  267.         default:
  268.             printf("\n(Y or N) \n");
  269.         }
  270.     }
  271. }
  272.  
  273. /* put a string like "   ^\n" on the console, left padded with spaces
  274.  *  so that the '^' character is below string[index] on the screen.
  275.  * allow for tabs in the source string
  276.  */
  277. putpointer(string, index, offset)
  278. char *string;
  279. short index, offset;
  280. {
  281.     short i;
  282.  
  283.     while (offset--)
  284.         printf(" ");
  285.     for (i = 0; i < index; ++i)
  286.         printf(string[i] == '\t'? "\t": " ");
  287.     printf("^\n");
  288. }
  289. 
  290.     while (offset--)
  291.         printf(" ");
  292.     for (i =